package com.dl698.axdr;

import com.dl698.asn1.axdr.AxdrType;
import com.dl698.util.ReverseByteArrayInputStream;
import com.dl698.util.ReverseByteArrayOutputStream;

import java.io.IOException;

/**
 * M698pdu类
 * 实现698协议数据单元的编解码
 * 
 * @author wind
 * @version 1.1.1
 */
public class M698pdu implements AxdrType {

    private byte[] dataCode = null;
    private Choice choice = Choice._ERR_NONE_SELECTED;
    private Get_Request get_request = null;
    private Set_Request set_request = null;
    private Action_Request action_request = null;
    private Security_Request security_request = null;
    private Connect_Request connect_request = null;
    private Proxy_Request proxy_request = null;
    private Get_Response get_response = null;
    private Set_Response set_response = null;
    private Action_Response action_response = null;
    private Proxy_Response proxy_response = null;
    private Security_Response security_response = null;
    private Connect_Response connect_response = null;

    // 添加缺失的请求字段
    private GetRequestNormal getRequest = null;
    private GetRequestNormalList getRequestList = null;
    private GetRequestRecord getRequestRecord = null;
    private SetRequestNormal setRequest = null;
    private ActionRequest actionRequest = null;
    private ActionRequestList actionRequestList = null;

    // 添加缺失的响应字段
    private GetResponseNormal getResponse = null;
    private GetResponseNormalList getResponseList = null;
    private GetResponseRecord getResponseRecord = null;
    private SetResponseNormal setResponse = null;
    private ActionResponseNormal actionResponse = null;
    private ActionResponseNormalList actionResponseList = null;

    /**
     * Choice枚举
     * 定义698协议数据单元的选择枚举值
     */
    public enum Choice {
        _ERR_NONE_SELECTED(-1),
        CONNECT_REQUEST(2),
        GET_REQUEST(5),
        SET_REQUEST(6),
        ACTION_REQUEST(7),
        PROXY_REQUEST(9),
        SECURITY_REQUEST(16),
        GET_RESPONSE(133),
        SET_RESPONSE(134),
        CONNECT_RESPONSE(130),
        ACTION_RESPONSE(135),
        PROXY_RESPONSE(137),
        SECURITY_RESPONSE(144);

        private final int value;

        Choice(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public static Choice fromValue(int value) {
            for (Choice choice : Choice.values()) {
                if (choice.value == value) {
                    return choice;
                }
            }
            return _ERR_NONE_SELECTED;
        }
    }

    /**
     * 默认构造函数
     */
    public M698pdu() {
    }

    /**
     * 获取实例
     * 
     * @return M698pdu实例
     */
    public static M698pdu getInstance() {
        return new M698pdu();
    }

    /**
     * 设置数据编码
     * 
     * @param dataCode 数据编码
     */
    public void setDataCode(byte[] dataCode) {
        this.dataCode = dataCode;
    }

    /**
     * 设置获取请求
     * 
     * @param getRequest 获取请求
     */
    public void setGet_Request(Get_Request getRequest) {
        this.resetChoices();
        this.choice = Choice.GET_REQUEST;
        // 根据Get_Request的选择类型设置相应的字段
        if (getRequest.getChoiceIndex() == GetRequestChoice.GET_REQUEST_NORMAL) {
            this.getRequest = getRequest.getGetRequestNormal();
        } else if (getRequest.getChoiceIndex() == GetRequestChoice.GET_REQUEST_NORMAL_LIST) {
            this.getRequestList = getRequest.getGetRequestNormalList();
        } else if (getRequest.getChoiceIndex() == GetRequestChoice.GET_REQUEST_RECORD) {
            this.getRequestRecord = getRequest.getGetRequestRecord();
        }
    }

    /**
     * 设置获取请求列表
     * 
     * @param getRequestList 获取请求列表
     */
    public void setGetRequestList(GetRequestNormalList getRequestList) {
        this.resetChoices();
        this.choice = Choice.GET_REQUEST;
        this.getRequestList = getRequestList;
    }

    /**
     * 设置获取记录请求
     * 
     * @param getRequestRecord 获取记录请求
     */
    public void setGetRequestRecord(GetRequestRecord getRequestRecord) {
        this.resetChoices();
        this.choice = Choice.GET_REQUEST;
        this.getRequestRecord = getRequestRecord;
    }

    /**
     * 设置设置请求
     * 
     * @param setRequest 设置请求
     */
    public void setSetRequest(SetRequestNormal setRequest) {
        this.resetChoices();
        this.choice = Choice.SET_REQUEST;
        this.setRequest = setRequest;
    }

    /**
     * 设置动作请求
     * 
     * @param actionRequest 动作请求
     */
    public void setActionRequest(ActionRequest actionRequest) {
        this.resetChoices();
        this.choice = Choice.ACTION_REQUEST;
        this.actionRequest = actionRequest;
    }

    /**
     * 设置动作请求列表
     * 
     * @param actionRequestList 动作请求列表
     */
    public void setActionRequestList(ActionRequestList actionRequestList) {
        this.resetChoices();
        this.choice = Choice.ACTION_REQUEST;
        this.actionRequestList = actionRequestList;
    }

    /**
     * 设置动作请求
     * 
     * @param actionRequest 动作请求
     */
    public void setAction_Request(Action_Request actionRequest) {
        this.resetChoices();
        this.choice = Choice.ACTION_REQUEST;
        // 根据Action_Request的选择类型设置相应的字段
        if (actionRequest.getChoiceIndex() == ActionRequestChoice.ACTION_REQUEST_NORMAL) {
            ActionRequestNormal actionRequestNormal = actionRequest.getActionRequestNormal();
            this.actionRequest = new ActionRequest();
            // 从ActionRequestNormal中提取数据并设置到ActionRequest中
            this.actionRequest.setAll(actionRequestNormal.getPiid(), actionRequestNormal.getOmd(),
                    actionRequestNormal.getData());
        } else if (actionRequest.getChoiceIndex() == ActionRequestChoice.ACTION_REQUEST_LIST) {
            this.actionRequestList = actionRequest.getActionRequestList();
        } else if (actionRequest.getChoiceIndex() == ActionRequestChoice.ACTION_THEN_GET_REQUEST_NORMAL_LIST) {
            // 这里可能需要特殊处理
            // 暂时设置为null，因为M698pdu中没有对应的字段
            this.actionRequest = null;
            this.actionRequestList = null;
        }
    }

    /**
     * 设置连接请求
     * 
     * @param connect_request 连接请求
     */
    public void setConnect_Request(Connect_Request connect_request) {
        this.resetChoices();
        this.choice = Choice.CONNECT_REQUEST;
        this.connect_request = connect_request;
    }

    /**
     * 设置安全请求
     * 
     * @param security_request 安全请求
     */
    public void setSecurity_Request(Security_Request security_request) {
        this.resetChoices();
        this.choice = Choice.SECURITY_REQUEST;
        this.security_request = security_request;
    }

    /**
     * 设置代理请求
     * 
     * @param proxy_request 代理请求
     */
    public void setProxy_Request(Proxy_Request proxy_request) {
        this.resetChoices();
        this.choice = Choice.PROXY_REQUEST;
        this.proxy_request = proxy_request;
    }

    /**
     * 设置代理响应
     * 
     * @param proxy_response 代理响应
     */
    public void setProxy_Response(Proxy_Response proxy_response) {
        this.resetChoices();
        this.choice = Choice.PROXY_RESPONSE;
        this.proxy_response = proxy_response;
    }

    /**
     * 设置安全响应
     * 
     * @param security_response 安全响应
     */
    public void setSecurity_Response(Security_Response security_response) {
        this.resetChoices();
        this.choice = Choice.SECURITY_RESPONSE;
        this.security_response = security_response;
    }

    /**
     * 设置连接响应
     * 
     * @param connect_response 连接响应
     */
    public void setConnect_Response(Connect_Response connect_response) {
        this.resetChoices();
        this.choice = Choice.CONNECT_RESPONSE;
        this.connect_response = connect_response;
    }

    /**
     * 设置获取响应
     * 
     * @param get_response 获取响应
     */
    public void setGet_Response(Get_Response get_response) {
        this.resetChoices();
        this.choice = Choice.GET_RESPONSE;
        this.get_response = get_response;
    }

    /**
     * 设置设置响应
     * 
     * @param set_response 设置响应
     */
    public void setSet_Response(Set_Response set_response) {
        this.resetChoices();
        this.choice = Choice.SET_RESPONSE;
        this.set_response = set_response;
    }

    /**
     * 设置动作响应
     * 
     * @param action_response 动作响应
     */
    public void setAction_Response(Action_Response action_response) {
        this.resetChoices();
        this.choice = Choice.ACTION_RESPONSE;
        this.action_response = action_response;
    }

    @Override
    public int decode(ReverseByteArrayInputStream input) {
        try {
            int codeLength = 0;
            com.dl698.asn1.axdr.AxdrEnum choosen = new com.dl698.asn1.axdr.AxdrEnum();
            choosen.setConst();

            codeLength += choosen.decode(input);
            this.resetChoices();
            this.choice = Choice.fromValue((int) choosen.getValue());

            switch (this.choice) {
                case GET_REQUEST:
                    this.get_request = new Get_Request();
                    codeLength += this.get_request.decode(input);
                    break;
                case SET_REQUEST:
                    this.set_request = new Set_Request();
                    codeLength += this.set_request.decode(input);
                    break;
                case ACTION_REQUEST:
                    this.action_request = new Action_Request();
                    codeLength += this.action_request.decode(input);
                    break;
                case CONNECT_REQUEST:
                    this.connect_request = new Connect_Request();
                    codeLength += this.connect_request.decode(input);
                    break;
                case SECURITY_REQUEST:
                    this.security_request = new Security_Request();
                    codeLength += this.security_request.decode(input);
                    break;
                case PROXY_REQUEST:
                    this.proxy_request = new Proxy_Request();
                    codeLength += this.proxy_request.decode(input);
                    break;
                case GET_RESPONSE:
                    this.get_response = new Get_Response();
                    codeLength += this.get_response.decode(input);
                    break;
                case SET_RESPONSE:
                    this.set_response = new Set_Response();
                    codeLength += this.set_response.decode(input);
                    break;
                case ACTION_RESPONSE:
                    this.action_response = new Action_Response();
                    codeLength += this.action_response.decode(input);
                    break;
                case CONNECT_RESPONSE:
                    this.connect_response = new Connect_Response();
                    codeLength += this.connect_response.decode(input);
                    break;
                case PROXY_RESPONSE:
                    this.proxy_response = new Proxy_Response();
                    codeLength += this.proxy_response.decode(input);
                    break;
                case SECURITY_RESPONSE:
                    this.security_response = new Security_Response();
                    codeLength += this.security_response.decode(input);
                    break;
                default:
                    throw new RuntimeException("Error decoding M698pdu: Unknown choice");
            }

            return codeLength;
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error decoding M698pdu", e);
        }
    }

    @Override
    public int encode(ReverseByteArrayOutputStream output) {
        try {
            if (this.dataCode != null) {
                for (int i = this.dataCode.length - 1; i >= 0; i--) {
                    output.write(this.dataCode[i]);
                }
                return this.dataCode.length;
            }

            if (this.choice == Choice._ERR_NONE_SELECTED) {
                throw new RuntimeException("Error encoding M698pdu: No item in choice was selected.");
            }

            int codeLength = 0;

            if (this.choice == Choice.GET_REQUEST) {
                if (this.get_request != null) {
                    codeLength += this.get_request.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(5);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("get_request is null");
                }
            } else if (this.choice == Choice.SET_REQUEST) {
                if (this.set_request != null) {
                    codeLength += this.set_request.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(6);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("set_request is null");
                }
            } else if (this.choice == Choice.ACTION_REQUEST) {
                if (this.action_request != null) {
                    codeLength += this.action_request.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(7);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("action_request is null");
                }
            } else if (this.choice == Choice.CONNECT_REQUEST) {
                if (this.connect_request != null) {
                    codeLength += this.connect_request.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(2);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("connect_request is null");
                }
            } else if (this.choice == Choice.SECURITY_REQUEST) {
                if (this.security_request != null) {
                    codeLength += this.security_request.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(16);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("security_request is null");
                }
            } else if (this.choice == Choice.PROXY_REQUEST) {
                if (this.proxy_request != null) {
                    codeLength += this.proxy_request.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(9);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("proxy_request is null");
                }
            } else if (this.choice == Choice.GET_RESPONSE) {
                if (this.get_response != null) {
                    codeLength += this.get_response.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(133);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("get_response is null");
                }
            } else if (this.choice == Choice.SET_RESPONSE) {
                if (this.set_response != null) {
                    codeLength += this.set_response.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(134);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("set_response is null");
                }
            } else if (this.choice == Choice.ACTION_RESPONSE) {
                if (this.action_response != null) {
                    codeLength += this.action_response.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(135);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("action_response is null");
                }
            } else if (this.choice == Choice.CONNECT_RESPONSE) {
                if (this.connect_response != null) {
                    codeLength += this.connect_response.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(130);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("connect_response is null");
                }
            } else if (this.choice == Choice.PROXY_RESPONSE) {
                if (this.proxy_response != null) {
                    codeLength += this.proxy_response.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(137);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("proxy_response is null");
                }
            } else if (this.choice == Choice.SECURITY_RESPONSE) {
                if (this.security_response != null) {
                    codeLength += this.security_response.encode(output);
                    com.dl698.asn1.axdr.AxdrEnum c = new com.dl698.asn1.axdr.AxdrEnum();
                    c.setMinMaxVal(144);
                    codeLength += c.encode(output);
                    return codeLength;
                } else {
                    throw new RuntimeException("security_response is null");
                }
            }

            throw new RuntimeException("Error encoding M698pdu: No item in choice was encoded.");
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException("Error encoding M698pdu", e);
        }
    }

    /**
     * 重置选择
     */
    public void resetChoices() {
        this.choice = Choice._ERR_NONE_SELECTED;
        this.get_request = null;
        this.set_request = null;
        this.action_request = null;
        this.security_request = null;
        this.connect_request = null;
        this.proxy_request = null;
        this.get_response = null;
        this.set_response = null;
        this.action_response = null;
        this.proxy_response = null;
        this.security_response = null;
        this.connect_response = null;
        // 重置额外的字段
        this.getRequest = null;
        this.getRequestList = null;
        this.getRequestRecord = null;
        this.setRequest = null;
        this.actionRequest = null;
        this.actionRequestList = null;
        this.getResponse = null;
        this.getResponseList = null;
        this.getResponseRecord = null;
        this.setResponse = null;
        this.actionResponse = null;
        this.actionResponseList = null;
    }

    /**
     * 获取选择枚举
     * 
     * @return Choice枚举值
     */
    public Choice getChoice() {
        return this.choice;
    }

    /**
     * 获取选择枚举值
     * 
     * @return Choice枚举值
     */
    public int getChoiceValue() {
        return this.choice.getValue();
    }

    @Override
    public String toString() {
        switch (this.choice) {
            case GET_REQUEST:
                if (this.get_request != null) {
                    return "choice: {get_request: " + this.get_request + "}";
                } else {
                    return "choice is get_request but get_request is null";
                }
            case SET_REQUEST:
                if (this.set_request != null) {
                    return "choice: {set_request: " + this.set_request + "}";
                } else {
                    return "choice is set_request but set_request is null";
                }
            case ACTION_REQUEST:
                if (this.action_request != null) {
                    return "choice: {action_request: " + this.action_request + "}";
                } else {
                    return "choice is action_request but action_request is null";
                }
            case CONNECT_REQUEST:
                if (this.connect_request != null) {
                    return "choice: {connect_request: " + this.connect_request + "}";
                } else {
                    return "choice is connect_request but connect_request is null";
                }
            case SECURITY_REQUEST:
                if (this.security_request != null) {
                    return "choice: {security_request: " + this.security_request + "}";
                } else {
                    return "choice is security_request but security_request is null";
                }
            case PROXY_REQUEST:
                if (this.proxy_request != null) {
                    return "choice: {proxy_request: " + this.proxy_request + "}";
                } else {
                    return "choice is proxy_request but proxy_request is null";
                }
            case GET_RESPONSE:
                if (this.get_response != null) {
                    return "choice: {get_response: " + this.get_response + "}";
                } else {
                    return "choice is get_response but get_response is null";
                }
            case SET_RESPONSE:
                if (this.set_response != null) {
                    return "choice: {set_response: " + this.set_response + "}";
                } else {
                    return "choice is set_response but set_response is null";
                }
            case ACTION_RESPONSE:
                if (this.action_response != null) {
                    return "choice: {action_response: " + this.action_response + "}";
                } else {
                    return "choice is action_response but action_response is null";
                }
            case CONNECT_RESPONSE:
                if (this.connect_response != null) {
                    return "choice: {connect_response: " + this.connect_response + "}";
                } else {
                    return "choice is connect_response but connect_response is null";
                }
            case PROXY_RESPONSE:
                if (this.proxy_response != null) {
                    return "choice: {proxy_response: " + this.proxy_response + "}";
                } else {
                    return "choice is proxy_response but proxy_response is null";
                }
            case SECURITY_RESPONSE:
                if (this.security_response != null) {
                    return "choice: {security_response: " + this.security_response + "}";
                } else {
                    return "choice is security_response but security_response is null";
                }
            default:
                return "unknown";
        }
    }

    // 添加getter方法
    public Get_Request getGet_Request() {
        return this.get_request;
    }

    public Set_Request getSet_Request() {
        return this.set_request;
    }

    public Action_Request getAction_Request() {
        return this.action_request;
    }

    public Security_Request getSecurity_Request() {
        return this.security_request;
    }

    public Connect_Request getConnect_Request() {
        return this.connect_request;
    }

    public Proxy_Request getProxy_Request() {
        return this.proxy_request;
    }

    public Get_Response getGet_Response() {
        return this.get_response;
    }

    public Set_Response getSet_Response() {
        return this.set_response;
    }

    public Action_Response getAction_Response() {
        return this.action_response;
    }

    public Proxy_Response getProxy_Response() {
        return this.proxy_response;
    }

    public Security_Response getSecurity_Response() {
        return this.security_response;
    }

    public Connect_Response getConnect_Response() {
        return this.connect_response;
    }
}